<?php
#+------------------------------------------------------------------
#| 普通的。
#+------------------------------------------------------------------
#| Author:Janmas Cromwell <janmas-cromwell@outlook.com>
#+------------------------------------------------------------------
class NodeList
{
    protected $header;
    protected $size;

    public function __construct()
    {
        $this->init();
    }

    protected function init($key = 'Header', $next = null)
    {
        $this->header = new Node($key, $next);
        $this->size = 0;
    }

    /**
     * 新增
     * @param $index
     * @param $value
     * @throws Exception
     */
    public function add($index, $value)
    {
        if ($index > $this->size) {
            throw new Exception('超过链表范围');
        }
        if (!is_string($value)) {
            throw new Exception('请输入字符串');
        }

        $prev = $this->header;
        for ($i = 0; $i < $index; $i++) {
            $prev = $prev->next;
        }
        $prev->next = new Node($value, $prev->next);
        $this->size++;
    }

    /**
     * 编辑
     * @param $index
     * @param $value
     * @throws Exception
     */
    public function update($index, $value)
    {
        if ($index > $this->size || $index <= 0) {
            throw new Exception('索引超过链表范围');
        }
        $prev = $this->header;
        for ($i = 0; $i <= $index; ++$i) {
            if ($i == $index) {
                $prev->data = $value;
            }
            $prev = $prev->next;
        }
    }

    /**
     * 移除指定节点
     * @param $index
     * @throws Exception
     */
    public function remove($index)
    {
        if ($index > $this->size || $index < 0) {
            throw new Exception('超过链表的范围');
        }

        $prev = $this->header;
        for ($i = 0; $i <= $index; $i++) {
            if ($i == $index) {
                $prev->next = $prev->next->next;
            }
            $prev = $prev->next;
        }
        $this->size--;
    }

    /**
     * 查找指定节点
     * @param $index
     * @return mixed|void|null
     * @throws Exception
     */
    public function select($index)
    {
        if ($index > $this->size || $index <= 0) {
            throw new Exception('索引超过链表范围');
        }
        $prev = $this->header;
        for ($i = 0; $i <= $index; ++$i) {
            if ($i == $index) {
                return $prev->data;
            }
            $prev = $prev->next;
        }
    }

    /**
     * 从尾部弹出一个并删除
     * @return mixed|void|null
     * @throws Exception
     */
    public function pop()
    {
        $result = $this->select($this->size);
        $this->remove($this->size);
        return $result;
    }

    /**
     * 从头部弹出一个并删除
     * @return mixed|void|null
     * @throws Exception
     */
    public function shift()
    {
        $result = $this->select(1);
        $this->remove(0);
        return $result;
    }

    /**
     * 从尾部入
     * @param $value
     * @throws Exception
     */
    public function push($value)
    {
        $this->add($this->size, $value);
    }

    /**
     * 从头部入
     * @param $value
     * @throws Exception
     */
    public function unshift($value)
    {
        $this->add(0, $value);
        ++$this->size;
    }

    /**
     * 反转
     * @throws Exception
     */
    public function flip()
    {
        $new = null;
        $head = clone $this->header->next;
        while ($head) {
            $next = clone $head;
            $next = $next->next;
            $head->next = $new;
            $new = $head;
            $head = $next;
        }

        $this->header = new Node('Header', $new);
        return $new;
    }

    /**
     * 转换为string
     * @return string
     */
    public function tostring()
    {
        return (string)$this;
    }

    public function __tostring()
    {
        $prev = $this->header->next;
        while ($prev) {
            $r[] = (string)$prev->data;
            $prev = $prev->next;
        }
        return implode('->', $r);
    }

}
